﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using StackExchange.Redis;

namespace Moolink.Helper
{

    public class RedisHelper
    {
        // redis config
        private static ConfigurationOptions configurationOptions = ConfigurationOptions.Parse("r-bp156c79a67bb3c4pd.redis.rds.aliyuncs.com:6379,password=Redis7229026,connectTimeout=2000");
        //the lock for singleton
        private static readonly object Locker = new object();
        //singleton
        private static ConnectionMultiplexer redisConn;
        //singleton
        public static bool getRedisConn()
        {
            if (redisConn == null)
            {
                lock (Locker)
                {
                    if (redisConn == null || !redisConn.IsConnected)
                    {
                        redisConn = ConnectionMultiplexer.Connect(configurationOptions);
                    }
                }
            }
            else if(!redisConn.IsConnected&&!redisConn.IsConnecting)
			{
                lock (Locker)
                {
                    if (!redisConn.IsConnected)
                    {
                        redisConn.Close();
                        redisConn.Dispose();
                        redisConn = null;
                        redisConn = ConnectionMultiplexer.Connect(configurationOptions);
                    }
                }
            }

            return redisConn.IsConnected;
        }

        public static bool SetStringValue(string strKey, string strValue, int ExpSec = 55 * 60, int dbn = 1)
        {
            if(getRedisConn())
			{
                var db = redisConn.GetDatabase(dbn);

                //set get
                bool setResult = db.StringSet(strKey, strValue);
                //Console.WriteLine("set " + strKey + " " + strValue + ", result is " + setResult);

                //expire
                if (ExpSec > 0) db.KeyExpire(strKey, new TimeSpan(0, 0, ExpSec));
                //Console.WriteLine("expire " + strKey + ", after 5 seconds, value is " + db.StringGet(strKey));
                return setResult;
            }
            return false;



        }
        public static bool SetHashValue(string sKey, string hashKey, string hashValue, int ExpSec = 55 * 60, int dbn = 1)
        {
            if (getRedisConn())
            {
                var db = redisConn.GetDatabase(dbn);

                //set get
                bool setResult = db.HashSet(sKey, hashKey, hashValue);
                //Console.WriteLine("set " + strKey + " " + strValue + ", result is " + setResult);

                //expire
                //if (ExpSec > 0) db.KeyExpire(strKey, new TimeSpan(0, 0, ExpSec));
                //Console.WriteLine("expire " + strKey + ", after 5 seconds, value is " + db.StringGet(strKey));

                return setResult;
            }
            return false;
        }
        public static string GetHashValue(string sKey, string hashKey, int dbn = 1)
        {
            if (getRedisConn())
            {
                var db = redisConn.GetDatabase(dbn);
                RedisValue value = db.HashGet(sKey, hashKey);
                return value;
            }
            return null;
        }
        public static Dictionary<string,string> GetHashValue(string sKey, int dbn = 1)
        {
            if (getRedisConn())
            {
                var db = redisConn.GetDatabase(dbn);
                HashEntry[] value = db.HashGetAll(sKey);
                Dictionary<string, string> valuestr = new Dictionary<string, string>();
                foreach (var item in value)
                {
                    valuestr.Add(item.Name.ToString(), item.Value.ToString());
                }
                return valuestr;
            }
            return null;
        }

        public static string GetStringValueWithExpiry(string strKey, ref DateTime time, int dbn = 1)
        {
            if (getRedisConn())
            {
                var db = redisConn.GetDatabase(dbn);
                RedisValueWithExpiry value_exp = db.StringGetWithExpiry(strKey);
                if (value_exp.Expiry != null)
                    time = DateTime.Now.Add((TimeSpan)value_exp.Expiry);
                else
                    time = DateTime.MinValue;
                return value_exp.Value;
            }
            return null;
        }

        public static string GetStringValue(string strKey, int dbn = 1)
        {
            if (getRedisConn())
            {
                var db = redisConn.GetDatabase(dbn);
                RedisValue value = db.StringGet(strKey);
                return value;
            }
            return null;
        }


        public static string GetRingListValue(string strKey, int dbn = 1)
        {
            if (getRedisConn())
            {
                var db = redisConn.GetDatabase(dbn);
                RedisValue value = db.ListRightPopLeftPush(strKey, strKey);
                return value;
            }
            return null;
        }




    }
}
